<inherits name="org.jboss.errai.ui.Cordova"/>
Starting with version 2.4.0, Errai now supports mobile development. One of the modules that makes this feasible is the Cordova module. It offers a way to integrate with native hardware in an Errai way.
Add the following to your application's .gwt.xml module file:
<inherits name="org.jboss.errai.ui.Cordova"/>
When the Cordova module is included you can integrate with native hardware by injecting the native components into your code:
@Templated("#main") public class KitchenSinkClient extends Composite { @Inject Camera camera; @Inject @DataField Button takePicture; @EventHandler("takePicture") public void onTakePicktureClicked(ClickEvent event) { PictureOptions options = new PictureOptions(25); options.setDestinationType(PictureOptions.DESTINATION_TYPE_DATA_URL); options.setSourceType(PictureOptions.PICTURE_SOURCE_TYPE_CAMERA); camera.getPicture(options, new PictureCallback() { @Override public void onSuccess(String data) { image.setUrl(UriUtils.fromSafeConstant("data:image/jpeg;base64," + data)); } @Override public void onFailure(String error) { setGeneralErrorMessage("Could not take picture: " + error); } }); }
The components that are supported come from the gwt-phonegap project have a look there form more documentation.
Here are the native hardware components you can inject:
Camera
Accelerometer
Contacts
Capture (Provides access to the audio, image, and video capture capabilities of the device).
Compass
Notification (see documentation on phonegap site)
File create a native file
Device Get general information about the device.
So to integrate with these things all we have to do is @Inject these classes. There are also a couple of CDI events one can observe to be informed about hardware state:
BackButtonEvent
BatteryCriticalEvent
BatteryEvent
BatteryLowEvent
BatteryStatusEvent
EndCallButtonEvent
MenuButtonEvent
OffLineEvent
OnlineEvent
PauseEvent
ResumeEvent
SearchButtonEvent
StartCallButtonEvent
VolumeDownButtonEvent
VolumeUpButtonEvent
Example of how to use these events:
private void batteryIsLow(@Observes BatteryLowEvent event) { //mission accomplished. we can stop the infinite loop now. }
All that is left to do is build this and put it on a actual device. In order to make this as easy as possible we have a maven plugin that will create a native binary that you can install on a device. It will put the html and javascript of you application in a cordova application, because by doing so the client is no longer servered by the server the client will need to know how it can reach the server to do that place the following in your gwt.xml:
<replace-with class="com.company.application.Config"> <when-type-is class="org.jboss.errai.bus.client.framework.Configuration" /> </replace-with>
This class must implement org.jboss.errai.bus.client.framework.Configuration and return the url where the server is configured.
import org.jboss.errai.bus.client.framework.Configuration; public class Config implements Configuration { @Override public String getRemoteLocation() { // you probably want to do something environment specify here instead of something like this: return "https://grocery-edewit.rhcloud.com/errai-jpa-demo-grocery-list"; } }
Now all that is left is to add the plugin to the pom.xml like so:
<build> ... <plugins> <plugin> <groupId>org.jboss.errai</groupId> <artifactId>cordova-maven-plugin</artifactId> <version>${errai.version}</version> </plugin>
Now you can execute a native build with the following maven command:
#will build all supported platforms for now only ios and android mvn cordova:build-project #only build android mvn cordova:build-project -Dplatform=android #start the ios emulator with the deployed application mvn cordova:emulator -Dplatform=ios
For these to work you'll need to have the SDK's installed and on your path! In case of android you will additionally have to have ANDROID_HOME environment variable set.
These wrappers allow your Errai client to talk to an AeroGear server. Also have a look at the documentation of the AeroGear project.
Pipes are for getting data from the server. Right now the only implementation is REST it will use Id to construct urls.
Pipe<Task> pipe = new PipeFactory().createPipe(Task.class, "tasks"); pipe.save(new Task(123, "new", "2012-01-01"), new AsyncCallback<Task>() { @Override public void onSuccess(Task result) { Window.alert("jipee saved a taks"); } @Override public void onFailure(Throwable caught) { } });
This will preform a PUT /tasks URL
Another concept that comes with AeroGear is Stores. Currently there are 2 Store types supported: Memory and SessionLocal. Memory is just a big javascript array to hold your data. Here is how you create and configure a Store:
Store<User> store = new DataManager().store(User.class); store.save(new User(2, "test2")); Collection<User> collection = store.readAll(); User user = store.read(2);
Pipes can be authenticated by just adding the authenticator into the Pipe and you are good to go.
Authenticator authenticator = new AuthenticationFactory().createAuthenticator("name"); Pipe<Task> pipe = new PipeFactory().createPipe(Task.class, "tasks", authenticator); authenticator.login(username.getText(), password.getText(), new AsyncCallback<String>() { @Override public void onSuccess(String result) { Window.alert("successful login"); } @Override public void onFailure(Throwable caught) { message.setText("Login failed, please try again"); } });
There is also a method called enroll() for adding new users.